/**
 * *********************************************
 * 光电上料机自控
 * V1.0
 * 25-3-5
 * 当前： 
 * 
 * io口定义 V
 * 
 * *********************************************
*/

#include "STC8H.H"
#include "io.h"
#include "stdint.h"
#include "ssd1315.h"
#include "INTRINS.H"
#include "eeprom.h"
#include "string.h"

//配置参数宏定义
#define _OPERATION_TIMEOUT_MAX_ 60 //最大超时60秒
#define _UP_DELAY_MAX_ 60 //上升延迟最大值60秒
#define _DOWN_DELAY_MAX_ 60 //下降延迟最大值60秒
//C语言NULL关键字宏定义
#ifdef __cplusplus
#define NULL 0
#else
#define NULL (void *)0
#endif
#pragma region 宏定义
/*********中断号*********/
#define EXT0_VECTOR 0  /* 0x03 external interrupt 0 */
#define TIM0_VECTOR 1  /* 0x0b timer 0 */
#define EXT1_VECTOR 2  /* 0x13 external interrupt 1 */
#define TIM1_VECTOR 3  /* 0x1b timer 1 */
#define UART0_VECTOR 4 /* 0x23 serial port 0 */
/******************* */

#define _STOP_HOLD_TIME_ 200  //停止保持时间 200ms

#pragma endregion 宏定义
/**************************/
// 状态定义
#pragma region 状态机组、菜单结构体
enum SYS_STATE { 
    STATE_MANUAL,
    STATE_AUTO,
    SETTING_STATE,
    STATE_TIMEOUT,
    STATE_ERROR

};
enum DIG_SELECT {
    _GE = 1,//个位
    _SHI,//十位
    _BAI,//百位
};

enum PLATE_STATE {
    POS_CORRECT,
    POS_OVER,
    POS_BELOW,
    POS_UNKOWN
};

enum OUT_STATE {
    up,
    down,
    stop,
    err
};

enum MENU_INDEX{
    SETTING_ROOT,
    SETTING_OPERATE_DELAY,
    SETTING_OPERATION_TIMEOUT,
    SETTING_UP_OPERATE_DELAY,
    SETTING_DOWN_OPERATE_DELAY
};
enum MENU_LEVEL{
    ROOT_LEVEL,
    L0_LEVEL,   //level0菜单层级
    L1_LEVEL    //level1菜单层级
};
typedef struct 
{
    uint8_t current;    // 当前菜单索引
    uint8_t level;      //当前菜单等级  
    uint8_t parent;     // 父菜单索引
    uint8_t child_num;  // 子菜单数量
    char title[20];     // 菜单标题
    int32_t value;      // 当前值
    void (*enter_func)(uint8_t); // 进入菜单执行函数
    uint16_t SAVE_ADDR;  // 参数保存地址
}MENU_ITEM;

enum BOARD_KEY{
        KEY_SET=1,  //防止返回空值为0时冲突
        KEY_LEFT,
        KEY_RIGHT,
        KEY_ENTER
};

#pragma endregion 状态机组、菜单结构体
// 全局变量
#pragma region 全局变量
//设置项
uint16_t UP_DELAY = 0;      //上升动作前延迟,ms
uint16_t DOWN_DELAY = 0;    //下降动作前延迟,ms
uint16_t OPERATION_TIMEOUT = 0xFFFF;      //自动升降超时,ms
//数值设置中间变量
//uint8_t sec_dig[3] = {0 , 0, 0};   //设置界面每个数字位数组 [0]:个位 [1]:十位 [2]:百位
uint8_t sec_num = 0xff;//读取参数数值
uint8_t sec_select = _GE;  //选中个位

uint8_t current_menu = SETTING_ROOT;        //当前菜单界面
uint8_t menu_cursor = SETTING_OPERATE_DELAY;         //高亮选项菜单索引
uint8_t menu_cursor_dis = 0;                //显示高亮行数
bit _setting_en = 0;                //初始化菜单循环使能
volatile enum SYS_STATE oprate_state = STATE_MANUAL;
volatile flash_en = 0;  //闪烁使能位
volatile enum PLATE_STATE plate_state = POS_CORRECT;
volatile enum OUT_STATE out_state = stop;
volatile uint16_t up_timeout_count = 0;
volatile uint16_t down_timeout_count = 0;
volatile uint16_t up_delay_count = 0;
volatile uint16_t down_delay_count = 0;
volatile uint16_t flash_count = 0;
volatile bit up_delay_flag = 0;    //为0时立即动作，下同
volatile bit down_delay_flag = 0;

volatile systick = 0; //系统滴答标志位

#pragma endregion 全局变量
// 函数声明
#pragma region 函数声明
//功能
void Settings_Init(void);
void Timer0_Init(void);
void Key_Scan(void);
void Plate_Scan(void);
void Auto_Mode(void);
void Manual_Mode(void);
bit Timeout_Detection(void);    //1超时
//void Delay_Detection(void);
uint8_t _OUT_(void);            //返回0正常

//菜单
void _setting_(void);
void _delay_soft_x10ms_(uint8_t _x10ms);//菜单软件延时10毫 秒
void _SETTING_ROOT_FUNC_(uint8_t _key);                     
void _SETTING_OPERATE_DELAY_(uint8_t _key);
void _SETTING_OPERATION_TIMEOUT_(uint8_t _key);
void _SETTING_UP_OPERATE_DELAY_(uint8_t _key);
void _SETTING_DOWN_OPERATE_DELAY_(uint8_t _key);
void _NUM_SET_(uint8_t _key, uint16_t _max, uint16_t _NUM_ADDR);//设置数值函数
uint8_t _board_key_scan_(uint8_t _before_delay_x10ms); //按键扫描函数

void MenuDisplayUpdate();
#pragma endregion 函数声明

//菜单变量
MENU_ITEM menu[] = {
    // 主界面（0级）
    {SETTING_ROOT, ROOT_LEVEL,0xff/*代表没有父级菜单*/, 2, "Setting", 0, _SETTING_ROOT_FUNC_, NULL},
    // 一级菜单项
    {SETTING_OPERATE_DELAY, L0_LEVEL,SETTING_ROOT, 2, "Operate Delay", 0, _SETTING_OPERATE_DELAY_, NULL},    // 延迟设置
    {SETTING_OPERATION_TIMEOUT, L0_LEVEL,SETTING_ROOT, 1, "Protect Timeout", 0, _SETTING_OPERATION_TIMEOUT_, 0x0000},  // 保护设置
    // 二级菜单 - 延迟设置（父级1）
    {SETTING_UP_OPERATE_DELAY,L1_LEVEL,SETTING_OPERATE_DELAY, 0, "Up Delay", 1000, _SETTING_UP_OPERATE_DELAY_, 0x0001},  // 上升延迟
    {SETTING_DOWN_OPERATE_DELAY, L1_LEVEL,SETTING_OPERATE_DELAY, 0, "Down Delay", 500, _SETTING_DOWN_OPERATE_DELAY_, 0x0002},   // 下降延迟
};


// 定时器0初始化
void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0xCD;				//设置定时初始值
	TH0 = 0xD4;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
    ET0 = 1;                //开启定时器0中断
}

// 定时器0中断服务函数
#pragma region 中断处理
void Timer0_ISR(void) interrupt 1
{
    systick = ~systick; //翻转滴答标志位
    if (up_delay_flag) up_delay_count++;
    if (down_delay_flag) down_delay_count++;
    if (flash_en) {
        if(flash_count < 150){
        flash_count++;}else{AUTO_LED = ~AUTO_LED; flash_count = 0;}
    }
    if (oprate_state == STATE_AUTO)
    {
        if (out_state == up) up_timeout_count++;
        if (out_state == down) down_timeout_count++;
    }
}
#pragma endregion 中断处理
/********************************核心功能*************************************/
#pragma region 核心功能

// 按键扫描函数
void Key_Scan(void)
{
    //菜单设置按键
    if (_set_b == 0){
        /*SOLENOID_VALVE = 0;
        OIL_PUMP = 0;
        out_state = stop;
        AUTO_LED = 0;   //OFF */
        oprate_state = SETTING_STATE ;
    }else if (DOWN_PEDAL == 0) // 下降踏板按下,优先级大于上升踏板，避免同时触发
    {
        oprate_state = STATE_MANUAL;
        //AUTO_LED = 0;
    }else if (UP_PEDAL == 0) // 上升踏板按下
    {
        oprate_state = STATE_MANUAL;
        //AUTO_LED = 0;
    }else if (AUTO_SWITCH == 0) // 自动模式开关按下
    {
        oprate_state = STATE_AUTO;
        //AUTO_LED = 1;
        // up_timeout_count = 0;
        // down_timeout_count = 0;
        //up_delay_count = 0;
        //down_delay_count = 0;
    }


}

void Plate_Scan()
{
    if(PHOTO_SWITCH_UP == 1 && PHOTO_SWITCH_DOWN == 0)
    {
        plate_state = POS_CORRECT ;
    }else if(PHOTO_SWITCH_UP == 0 && PHOTO_SWITCH_DOWN == 0)
    {
        plate_state = POS_OVER;
    }else if(PHOTO_SWITCH_UP == 1 && PHOTO_SWITCH_DOWN == 1)
    {
        plate_state = POS_BELOW;
    }
    // else if(PHOTO_SWITCH_UP == 0 && PHOTO_SWITCH_DOWN == 1){
    //     plate_state = POS_UNKOWN;
    // }
}

// 自动模式函数
// void Auto_Mode(void)
// {//延时控制变量在_OUT_函数中清零
//     if(!Timeout_Detection()){
//         switch (plate_state)
//         {
//         case POS_OVER:// 板材高度过高，需要下降
//             up_delay_flag = 0;//防止动作延时未触及时累加
//             up_timeout_count = 0;
//             if (!down_delay_flag && out_state != down )
//             {
//                 down_delay_flag = 1;
//                 down_delay_count = 0;
//             }
//             if (down_delay_flag && (down_delay_count >= DOWN_DELAY)) // 1s延时
//             {
//                 down_delay_flag = 0;
//                 out_state = down;
//             }
//             break;       
//         case POS_BELOW : // 板材高度过低，需要上升
//             down_delay_flag = 0;//防止动作延时未触及时累加
//             down_timeout_count = 0;
//             if (!up_delay_flag && out_state != up )
//             {
//                 up_delay_flag = 1;
//                 up_delay_count = 0;
//             }
//             if (up_delay_flag && (up_delay_count >= UP_DELAY)) //
//             {
//                 up_delay_flag = 0;
//                 out_state = up;
//             }
//             break;
//         case POS_CORRECT: // 板材高度合适
//             out_state = stop;
//             down_timeout_count = 0;
//             up_timeout_count = 0;
//             up_delay_flag = 0;  //防止动作延时未触及时累加
//             down_delay_flag = 0;//防止动作延时未触及时累加
//             break;
//         case POS_UNKOWN:
//             //oprate_state = STATE_ERROR;//切换到光电位置检测错误状态(由主函数停止输出)
//             //break;
//         default:
//             oprate_state = STATE_ERROR;//切换到未知错误状态（由主函数停止输出）
//             break;
//         }
//     }else{
//         oprate_state = STATE_TIMEOUT;//切换到超时错误状态（由主函数停止输出）
//     }
// }

void Auto_Mode(void)
{
    static uint16_t stop_hold_count = 0;  //停止保持计数
    static bit last_systick = 0;  //上次系统滴答状态

    if(!Timeout_Detection()){
        switch (plate_state)
        {
        case POS_OVER:// 板材高度过高，需要下降
            up_delay_flag = 0;//防止动作延时未触及时累加
            up_timeout_count = 0;
            if (!down_delay_flag && out_state != down )
            {
                down_delay_flag = 1;
                down_delay_count = 0;
            }
            if (down_delay_flag && (down_delay_count >= DOWN_DELAY)) // 延时
            {
                down_delay_flag = 0;
                out_state = down;
            }
            break;
        
        case POS_BELOW : // 板材高度过低，需要上升
            down_delay_flag = 0;//防止动作延时未触及时累加
            down_timeout_count = 0;
            if (!up_delay_flag && out_state != up )
            {
                up_delay_flag = 1;
                up_delay_count = 0;
            }
            if (up_delay_flag && (up_delay_count >= UP_DELAY))
            {
                up_delay_flag = 0;
                out_state = up;
            }
            break;

        case POS_CORRECT: // 板材高度合适
            if(out_state != stop)  //当前不是停止状态
            {
                stop_hold_count = 0;  //进入延时
            }
            
            if(systick != last_systick)  //每1ms计数一次
            {
                if(stop_hold_count < _STOP_HOLD_TIME_)
                {
                    stop_hold_count++;
                }
                else  //达到保持时间
                {
                    out_state = stop;
                    down_timeout_count = 0;
                    up_timeout_count = 0;
                    up_delay_flag = 0;   //防止动作延时未触及时累加
                    down_delay_flag = 0;  //防止动作延时未触及时累加
                }
            }
            last_systick = systick;
            break;

        default:
            oprate_state = STATE_ERROR;  //切换到未知错误状态 
            break;
        }
    }else{
        oprate_state = STATE_TIMEOUT;  //切换到超时错误状态
    }
}


// 手动模式函数
void Manual_Mode(void)
{
    if (DOWN_PEDAL == 0) //下降优先，防止同时触发
    {
        out_state = down;
    }else if (UP_PEDAL == 0)
    {
        out_state = up;
    }else
    {
        out_state = stop;
    }
}

// 超时检测函数
bit Timeout_Detection(void) //超时检测函数,1超时
{
    if (up_timeout_count >= OPERATION_TIMEOUT) // 上升超时5s
    {
        oprate_state = STATE_TIMEOUT;
        out_state = stop ;
        return 1;//超时
    }
    else if (down_timeout_count >= OPERATION_TIMEOUT) // 下降超时5s
    {
        oprate_state = STATE_TIMEOUT;
        out_state = stop;
        return 1;//超时
    }
    else{return 0;}//未超时
}
/*
// 延时检测函数
void Delay_Detection(void)
{
    if (up_delay_count >= 1000) up_delay_count = 0;
    if (down_delay_count >= 1000) down_delay_count = 0;
}*/

//输出
uint8_t _OUT_(void)
{
    static uint8_t last_out_state = stop;
    bit state_change = 0; //状态改变，用于共享状态切换信息
    if(last_out_state != out_state){up_delay_count = 0; down_delay_count = 0; last_out_state = out_state;state_change = 1;}//状态改变，清零延时计数器
    switch (out_state)
    {
    case up:
        SOLENOID_VALVE = 0;
        if(state_change){
        _delay_soft_x10ms_(10);}//延时100ms
        OIL_PUMP = 1;
        break;
    case down:
        OIL_PUMP = 0;
        if(state_change){
        _delay_soft_x10ms_(10);}//延时100ms
        SOLENOID_VALVE = 1;
        break;
    case stop:
        OIL_PUMP = 0;
        SOLENOID_VALVE = 0;
        break;
    default:
        break;
    }
    state_change = 0;//状态切换标志位清零
    return 0;//输出状态，未启用
}
#pragma endregion 核心功能


#pragma region 菜单功能

//菜单初始化函数
void Settings_Init(void)
{
    //初始化参数
    UP_DELAY = EEPROM_ReadByte(menu[SETTING_UP_OPERATE_DELAY].SAVE_ADDR) * 1000;
    DOWN_DELAY = EEPROM_ReadByte(menu[SETTING_DOWN_OPERATE_DELAY].SAVE_ADDR) * 1000;
    OPERATION_TIMEOUT = EEPROM_ReadByte(menu[SETTING_OPERATION_TIMEOUT].SAVE_ADDR)* 1000;
}
//菜单使用软件延时函数
void _delay_soft_x10ms_(volatile uint8_t _x10ms) //(X100毫秒)  //fosc 11.0592MHz
{
    volatile uint8_t i;
    for(i=0;i<_x10ms;i++)
    {
        //延时10ms
        volatile unsigned char data i, j;

        _nop_();
        _nop_();
        i = 144;
        j = 157;
        do
        {
            while (--j);
        } while (--i);
    }
}
// uint8_t _board_key_scan_(uint8_t _before_delay_x10ms){
 
//     //延迟函数，待合并后补
//     _delay_soft_x10ms_(_before_delay_x10ms);
//     if(!_set_b){
//         return KEY_SET;
//     }else if(!_left_b){
//         return KEY_LEFT;
//     }else if(!_right_b){
//         return KEY_RIGHT;
//     }else if(!_enter_b){
//         return KEY_ENTER;
//     }else{
//         return NULL;      //没有按键返回空值
//     }
// }

#pragma region 菜单功能函数
void _NUM_SET_(uint8_t _key, uint16_t _max, uint16_t _NUM_ADDR){
    uint8_t i;
    uint8_t sec_dig[3];//设置各位数值
    uint8_t sec_dis_dig[3];//显示数值字符串
    uint8_t menu_item_cnt;
    menu_item_cnt = sizeof(menu)/sizeof(menu[0]);//获取菜单总数

    sec_dig[0] = sec_num % 10; //个位
    sec_dig[1] = (sec_num / 10) % 10; //十位
    sec_dig[2] = (sec_num / 100) % 10; //百位
    sec_dis_dig[0] = sec_dig[0] + 0x30; //个位
    sec_dis_dig[1] = sec_dig[1] + 0x30; //十位
    sec_dis_dig[2] = sec_dig[2] + 0x30; //百位
    //显示更新
    switch (sec_select)//高亮选中
    {
    case _GE:
        DisplayChar(sec_dis_dig[0], 3, 56, 1); //个位
        DisplayChar(sec_dis_dig[1], 3, 48, 0); //十位
        DisplayChar(sec_dis_dig[2], 3, 40, 0); //百位
        break;
    case _SHI:
        DisplayChar(sec_dis_dig[0], 3, 56, 0); //个位
        DisplayChar(sec_dis_dig[1], 3, 48, 1); //十位
        DisplayChar(sec_dis_dig[2], 3, 40, 0); //百位
        break;
    case _BAI:
        DisplayChar(sec_dis_dig[0], 3, 56, 0); //个位
        DisplayChar(sec_dis_dig[1], 3, 48, 0); //十位
        DisplayChar(sec_dis_dig[2], 3, 40, 1); //百位
        break;
    default:
        break;
    }
    //显示单位
    DisplayString("x1 S", 3, 80,48,0,0); //显示单位
    switch (_key)
    {
        
    case KEY_SET:
        sec_select++;
        if(sec_select > _BAI) sec_select = _GE;
        break;
    case KEY_LEFT:
        switch (sec_select)
        {
        case _GE:
            if(sec_dig[0] > 0) sec_dig[0]--;
            else sec_dig[0] = 9;
            break;
        case _SHI:
            if(sec_dig[1] > 0) sec_dig[1]--;
            else sec_dig[1] = 9;
            break;
        case _BAI:
            if(sec_dig[2] > 0) sec_dig[2]--;
            else sec_dig[2] = 9;
            break;
        default:
            break;
        }
        // Check if total value exceeds _max
        if((sec_dig[2]*100 + sec_dig[1]*10 + sec_dig[0]) > _max) {
            sec_num = _max;
        }else{sec_num = sec_dig[2]*100 + sec_dig[1]*10 + sec_dig[0];}
        break;
    case KEY_RIGHT:
        switch (sec_select)
        {
        case _GE:
            if(sec_dig[0] < 9) sec_dig[0]++;
            else sec_dig[0] = 0;
            break;
        case _SHI:
            if(sec_dig[1] < 9) sec_dig[1]++;
            else sec_dig[1] = 0;
            break;
        case _BAI:
            if(sec_dig[2] < 9) sec_dig[2]++;
            else sec_dig[2] = 0;
            break;
        default:
            break;
        }
        // Check if total value exceeds _max
        if((sec_dig[2]*100 + sec_dig[1]*10 + sec_dig[0]) > _max) {
            sec_num = _max;
        }else{sec_num = sec_dig[2]*100 + sec_dig[1]*10 + sec_dig[0];}
        break;
    case KEY_ENTER:
        // 存储当前字节值到EEPROM
        EEPROM_SafeWriteByte(_NUM_ADDR, sec_num); //保存数值
        _delay_soft_x10ms_(10); // 延时100毫秒
        current_menu = menu[current_menu].parent;
                //更新menu_cursor
                for(i=0;i<=menu_item_cnt;i++){
                    if(menu[i].parent == current_menu){
                        menu_cursor = i; //获取根菜单光标
                        break;
                    }
                }
                ScreenTest();//清屏

    break;
    default:
    break;
    }
}
void _SETTING_ROOT_FUNC_(uint8_t _key){
    uint8_t i;
    uint8_t j;
    uint8_t menu_item_cnt;
    //显示更新
    //MenuDisplayUpdate();
    //显示更新
    menu_item_cnt = sizeof(menu)/sizeof(menu[0]);
    switch (_key)
    {
    case KEY_SET:
        _setting_en = 0;
        //menu_cursor = 0xff; //取消高亮
        //current_menu = 0xff; //取消当前菜单
        //MenuDisplayUpdate();//下一个显示循坏被跳过，主动刷新
        ScreenTest();//清屏
        oprate_state = STATE_MANUAL;
    break;
    case KEY_LEFT:

        for(i=menu_item_cnt-1;i>0;i--){
            j=(i+menu_cursor)%(menu_item_cnt);
            if(menu[j].parent == current_menu ){
                menu_cursor = j;            
                break;
            }
        }
    break;
    case KEY_RIGHT:
    for(i=1;i<menu_item_cnt;i++){
        j=(i+menu_cursor)%(menu_item_cnt);
        if(menu[j].parent == current_menu){
            menu_cursor = j;

            break;
        }
    }
    break;
    case KEY_ENTER:
        current_menu = menu_cursor;
        //更新menu_cursor
        for(i=0;i<=menu_item_cnt;i++){
            if(menu[i].parent == current_menu){
                menu_cursor = i; //获取根菜单光标
                break;
            }
        }
        ScreenTest();//清屏
        sec_num = EEPROM_ReadByte(menu[current_menu].SAVE_ADDR); //读取数值
    break;
    
    default:
    break;
    }
}
void _SETTING_OPERATE_DELAY_(uint8_t _key){
    uint8_t i;
    uint8_t j;
    uint8_t menu_item_cnt;
    menu_item_cnt = sizeof(menu)/sizeof(menu[0]);
    switch (_key)
    {
    case KEY_SET:
        current_menu = menu[current_menu].parent;
        //更新menu_cursor
        for(i=0;i<=menu_item_cnt;i++){
            if(menu[i].parent == current_menu){
                menu_cursor = i; //获取根菜单光标
                break;
            }
        }
        ScreenTest();//清屏
    break;
    case KEY_LEFT:
        for(i=menu_item_cnt-1;i>0;i--){
            j=(i+menu_cursor)%(menu_item_cnt);
            if(menu[j].parent == SETTING_OPERATE_DELAY){
                menu_cursor = j;
                break;
            }
        }
    break;
    case KEY_RIGHT:
        for(i=1;i<menu_item_cnt;i++){
        j=(i+menu_cursor)%(menu_item_cnt);
        if(menu[j].parent == SETTING_OPERATE_DELAY){
            menu_cursor = j;
            break;
        }
    }
    break;
    case KEY_ENTER:
        current_menu = menu_cursor;
        //更新menu_cursor
        sec_num = EEPROM_ReadByte(menu[current_menu].SAVE_ADDR); //读取数值
        ScreenTest();//清屏
    break;
    
    default:
        break;
    }
}
void _SETTING_OPERATION_TIMEOUT_(uint8_t _key ){
        _NUM_SET_(_key, _OPERATION_TIMEOUT_MAX_, menu[current_menu].SAVE_ADDR); //设置数值函数
}
void _SETTING_UP_OPERATE_DELAY_(uint8_t _key){
    _NUM_SET_(_key, _UP_DELAY_MAX_, menu[current_menu].SAVE_ADDR); //设置数值函数
}
void _SETTING_DOWN_OPERATE_DELAY_(uint8_t _key){
    _NUM_SET_(_key, _DOWN_DELAY_MAX_, menu[current_menu].SAVE_ADDR); //设置数值函数
}
#pragma endregion 菜单功能函数

//菜单核心
void _setting_(){
uint8_t i;
uint8_t menu_item_cnt;
_setting_en = 1;
current_menu = SETTING_ROOT;
menu_cursor = 0xff;//初始化光标
menu_item_cnt = sizeof(menu)/sizeof(menu[0]);
for(i=0;i<=menu_item_cnt;i++){
    if(menu[i].parent == current_menu){
        menu_cursor = i; //获取根菜单光标
        break;
    }
}

while(_setting_en)    //死循环关闭后续功能函数操作
{
    uint8_t board_key = 0;
    board_key = _board_key_scan_(5);    //循环扫描50ms
    MenuDisplayUpdate(); //菜单显示更新函数
    if(menu[current_menu].enter_func != NULL) {
        menu[current_menu].enter_func(board_key);}

}
Settings_Init(); //退出设置菜单，重新初始化设置参数
ScreenTest();//清屏
}

#pragma endregion 菜单功能
// 主函数
void main(void)
{
 volatile uint8_t last_operate_state = STATE_MANUAL; //保存上一次状态
 volatile bit state_change = 0; //状态改变，用于共享last_operate_state，因为循环逻辑中last_operate_state会被覆盖，无法使用两次
    P_SW2 |= 0x80;
    Timer0_Init();
    IO_Init();
    I2C_Init();
    SSD1315_Init();
    ScreenTest();
    DisplayString("Starting...", 3, 0,128,1, 0 );
    _delay_soft_x10ms_(100); // 1s延时
    ScreenTest(); //清屏
    EA = 1;
    /*//测试
    //测试反转显示
    DisplayString("Normal", 0, 0,128,1, 0 );
    DisplayString("Inverse", 2,0,128,0, 1 );

    //测试存储
    EEPROM_WriteFloat(0x0000, 52); //测试存储
    ceshi_temp = (uint8_t)EEPROM_ReadFloat(0x0000);
    DisplayString(&ceshi_temp,4,60,68,1,0); //测试读取
    ceshi_temp = 50;
    DisplayString(&ceshi_temp, 6, 40,88,1, 0 );

    while(1);
    //测试
    */
    //初始化设置参数
    //Settings_Init();
    while (1)
    {

        Key_Scan();     //按键扫描
        Plate_Scan();   //板材位置扫描

        if(last_operate_state != oprate_state)
        {
            if(last_operate_state >= STATE_TIMEOUT && oprate_state < STATE_TIMEOUT) //如果上次状态为错误或超时，且当前状态不报错，清屏
            {
                ScreenTest(); //清屏
            }
            state_change = 1; //状态改变
            last_operate_state = oprate_state; //更新上一次状态
        }
        switch (oprate_state)
        {
            case STATE_MANUAL:  //手动
                flash_en = 0;   //清除闪烁标志位
                AUTO_LED = 0;   //关闭自动灯
                Manual_Mode();  //手动处理函数
                break;
            case STATE_AUTO:    //自动
                if(state_change){
                    up_timeout_count = 0;
                    down_timeout_count = 0;
                    up_delay_count = 0;
                    down_delay_count = 0;
                    down_delay_flag = 0;
                    up_delay_flag = 0;
                }
                flash_en = 0;   //清除闪烁标志位
                AUTO_LED = 1;   //打开自动灯
                Auto_Mode();    //自动处理函数 
                break;  
            case STATE_TIMEOUT: //自动升降超时
                out_state = stop; //停止所有操作
                flash_en = 1;   //闪烁使能位
                //输出错误状态信息
                if(state_change)
                {
                    DisplayString("Error:", 1, 0,128,1, 1 );
                    DisplayString("OperationTimeout", 3, 0,128,1, 1 );
                }
                break;
            case STATE_ERROR:   //板材位置检测错误
                out_state = stop; //停止所有操作
                flash_en = 1;   //闪烁使能位
                //输出错误状态信息
                if(state_change)
                {
                    DisplayString("Error:", 1, 0,128,1, 1 );
                    DisplayString("PositionUnkown", 3, 0,128,1, 1 );
                }
                break;
            case SETTING_STATE:
                out_state = stop; //停止所有操作
                flash_en = 0;   //清除闪烁标志位
                AUTO_LED = 0; //关闭自动灯
                _OUT_(); //输出停止后打开设置菜单
                _setting_();
                break;
            default:
                break;
        }
        state_change = 0;   //切换状态标志位清零
        _OUT_();            //输出

    }
}
void MenuDisplayUpdate() {
    uint8_t i;
    uint8_t line = 2; // Start displaying menu items from line 1
    uint8_t menu_item_cnt = sizeof(menu) / sizeof(menu[0]);
    //if(current_menu == 0xff) return; // If no menu is selected, return

        // Display the title of the current menu in the center of page 0
        DisplayString(menu[current_menu].title, 0, 0, 128, 1, 0);

        // Iterate through the menu items to find children of the current menu
        for (i = 0; i < menu_item_cnt; i++) {
            if (menu[i].parent == current_menu) {
                // If this menu item is the currently selected item, display it in inverse
                if (i == menu_cursor) {
                    DisplayString(menu[i].title, line, 0, 128, 0, 1);
                } else {
                    DisplayString(menu[i].title, line, 0, 128, 0, 0);
                }
                line = line + 2; // Move to the next line for the next menu item
            }
        }
    
}
uint8_t _board_key_scan_(uint8_t _before_delay_x10ms){
    static uint8_t last_key = KEY_SET; // 存储上一次按键状态，SET以屏蔽首次开机触发
    uint8_t current_key = 0;

    /*延迟函数，待合并后补*/
    _delay_soft_x10ms_(_before_delay_x10ms);

    if(!_set_b){
        current_key = KEY_SET;
    }else if(!_left_b){
        current_key = KEY_LEFT;
    }else if(!_right_b){
        current_key = KEY_RIGHT;
    }else if(!_enter_b){
        current_key = KEY_ENTER;
    }

    if (current_key != 0 && current_key != last_key) {
        last_key = current_key; // 更新上一次按键状态
        return current_key; // 返回当前按键
    } else if (current_key == 0) {
        last_key = 0; // 没有按键按下，重置上一次按键状态
    }

    return 0; // 没有按键返回空值
}




